﻿#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable:6031)

//#include <iostream>
//using namespace std;
//#include <functional>
//
//// 定义一个仿函数
//struct DivideByTwo {
//    double operator()(double num) {
//        return num / 2.0;
//    }
//};
//
//// 定义一个函数
//double divideByThree(double num) {
//    return num / 3.0;
//}
//
//
//template <class F,class T>
//T useF(F f, T x)
//{
//    return f(x);
//}
//
//int main() {
//
//
//    // 直接使用仿函数
//    function<double(double)> func1 = DivideByTwo();
//    cout << useF(func1, 10.0) << endl;
//
//    // 直接使用函数指针
//    function<double(double)> func2 = divideByThree;
//    cout << useF(func2, 10.0) << endl;
//
//    //lambda表达式
//    function<double(double)> func3 = [](double d) {return d / 4; };
//    cout << useF(func3, 10.0) << endl;
//   
//
//    return 0;
//}

// 使用方法如下：
//#include <iostream>
//using namespace std;
//#include <functional>
//int f(int a, int b)
//{
//	return a + b;
//}
//struct Functor
//{
//public:
//	int operator() (int a, int b)
//	{
//		return a + b;
//	}
//};
//class Plus
//{
//public:
//	static int plusi(int a, int b)
//	{
//		return a + b;
//	}
//	double plusd(double a, double b)
//	{
//		return a + b;
//	}
//};
//int main()
//{
//	// 函数名(函数指针),
//	function<int(int, int)> func1 = f;//将函数指针传给包装器，就可以适配出具有相应函数指针的功能
//	cout << func1(1, 2) << endl;//调用的就是函数f，被调用函数的返回值类型是int,形参是int，int
//
//	// 函数对象
//	function<int(int, int)> func2 = Functor(); //将仿函数对象传给包装器，就可以适配出仿函数
//	cout << func2(1, 2) << endl;//调用的就是仿函数operator()，被调用仿函数的返回值类型是int,形参是int，int
//
//	// lambda表达式
//	function<int(int,int)> func3 = []( int a, int b){return a + b; };//将lambda传给包装器，就可以适配出lambda
//	cout << func3(1, 2) << endl;//调用的就是lambda，而其底层是仿函数，即调用对应的operator()，被调用仿函数的返回值类型是int,形参是int，int
//
//	// 类的成员函数，注意：成员函数取地址必须加&，由于是在类外，所以还得加上类域
//	function<int(int, int)> func4 = &Plus::plusi;//将静态成员函数指针传给包装器，就可以适配出具有相应成员函数指针的功能
//	cout << func4(1, 2) << endl;//调用的就是plusi函数
//
//	function<double(Plus*, double, double)> func5 = &Plus::plusd;//由于是非静态成员函数，其多了一个this指针，所以得多带上一个参数
//	//cout << func5(&Plus(), 1.1, 2.2) << endl;//由于plus()是一个匿名对象，属于右值，右值不能够取地址，所以不能这样写
//	Plus ps;//得额外定义一个对象
//	cout << func5(&ps, 1.1, 2.2) << endl;
//
//	//还可以这种写法，相当于用对象去调用了这个成员函数，可以认为是编译器的特殊处理
//	function<double(Plus, double, double)> func6 = &Plus::plusd;
//	cout << func6(Plus(), 1.1, 2.2) << endl;
//	return 0;
//}



// 使用举例
#include <iostream>
using namespace std;
#include <functional>
int Plus(int a, int b)
{
	return a + b;
}
class Sub
{
public:
	int sub(int a, int b)
	{
		return a - b;
	}
};
int main()
{
	//表示绑定函数plus 参数分别由调用 func1 的第一，二个参数指定，并用function包装器包装bind
	function<int(int, int)> func1 = bind(Plus, placeholders::_2, placeholders::_1);//绑定参数，_2代表func1的第二个参数在第一个位置，_1代表func2的第一个参数在第二个位置
	//相当于第一个参数替换成了2，第二个替换成了1，即1传给了b,2传给了a
	cout << func1(1, 2) << endl;//调用Plus函数

	//auto func1 = std::bind(Plus, placeholders::_1, placeholders::_2);
	

	//func2的类型为 function<void(int, int, int)> 与func1类型一样
	//表示绑定函数 plus 的第一，二为： 1， 2
	auto func2 = bind(Plus, 1, 2);//绑定参数，这些参数替换原来的参数，即func2的参数替换成了1,2
	cout << func2(2,3) << endl;//调用Plus函数


	// 绑定成员函数
	std::function<int(int, int)> func3 = std::bind(&Sub::sub, Sub(), placeholders::_1, placeholders::_2);
	cout << func3(1, 2) << endl;


	std::function<int(int, int)> func4 = std::bind(&Sub::sub, Sub(), placeholders::_2, placeholders::_1);
	cout << func4(1, 2) << endl;
	return 0;
}